﻿using ACC.Business;
using ACC.Business.Stn;
using ACC.Data;
using ACC.Data.Comm;
using ACC.Data.Line;
using ACC.Device;
using ACC.Device.PLC.Siemens;
using ACC.LineDevice.KukaPack;
using ACC.Util.Common;
using ACC.Util.DB;
using System;
using System.Linq;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;

namespace Script
{
    /// <summary>
    /// 安装钢扎带，人工
    /// </summary>
    public class L1M13130 : StnProcessKukaClientWithPLC
    {
        public L1M13130(StnRunningData data)
            : base(data)
        {
            PlcName = "PLC1201";
        }

        protected override void CreateBusinessLogic()
        {
            base.CreateBusinessLogic();
            //_lotChangeProcess = new LotChangeProcess_Ex(_data);
        }

        protected override ACCDevice CreateDevice()
        {
            ACCDevice dev = base.CreateDevice();
            if (kukaSiemensDev != null)
            {
                switch (_data.StnCfg.Name)
                {
                    case "L1M13131":
                        kukaSiemensDev.DB190_Offset = 10000;
                        break;
                    case "L1M13132":
                        kukaSiemensDev.DB190_Offset = 11000;
                        break;
                }

                kukaSiemensDev.DB190 = 800;
                kukaSiemensDev.DB192 = 80;
                kukaSiemensDev.DB193 = 800;
                kukaSiemensDev.DB194 = 800;
                kukaSiemensDev.DB192_PLC_Offset = (ushort)(kukaSiemensDev.DB190_Offset + 66);  // 10066;
                kukaSiemensDev.DB193_PLC_Offset = (ushort)(kukaSiemensDev.DB190_Offset + 34);  // 10034;
                kukaSiemensDev.DB193_ACC_Offset = (ushort)(kukaSiemensDev.DB190_Offset + 68);  // 10068;
                kukaSiemensDev.DB194_PLC_Offset = (ushort)(kukaSiemensDev.DB190_Offset + 34);  // 10034;
                kukaSiemensDev.DB194_PLC_Data_Offset = (ushort)(kukaSiemensDev.DB190_Offset + 76); // 10076;
            }

            return dev;

        }

        protected override void ClearBatchLotsWhenChangePartNo(RuningPartNo oldpartno, RuningPartNo newpartno)
        {
            if (oldpartno != null)
            {
                List<LotBatchData> sameLots = new List<LotBatchData>();
                ComponentSet oldSet = _data.GetComponentSet(oldpartno);
                ComponentSet newSet = _data.GetComponentSet(newpartno);

                if (oldSet != null && newSet != null)
                {
                    foreach (var key in oldSet.Items.Keys)
                    {
                        if (newSet.Items.ContainsKey(key))
                        {
                            BomItemCfg oldBom = oldSet.Items[key].BomItem;
                            BomItemCfg newBom = newSet.Items[key].BomItem;

                            //ItemPartNo + ItemRev一致视为同一种物料
                            if (oldBom.ItemPartNo.Equals(newBom.ItemPartNo) && oldBom.ItemRev.Equals(newBom.ItemRev))
                            {
                                foreach (var lotBatch in oldSet.Items[key].LotBatchDatas)
                                {
                                    if (lotBatch.Qty > 0)
                                    {
                                        sameLots.Add(lotBatch);
                                    }
                                }
                            }
                        }
                    }
                }
                _lotChangeProcess.DeleteAllLotBatchByStn(_data.StnCfg.LineCfg.Line, _data.StnCfg.OPCfg.OP, _data.StnCfg.Name, sameLots);
            }
        }
    }

    /// <summary>
    /// 重写物料加载逻辑，保留历史partno的物料
    /// </summary>
    public class LotChangeProcess_Ex : LotChangeProcess
    {
        public LotChangeProcess_Ex(StnRunningData data)
            : base(data)
        {
        }

        public override ACCCode DoLotChange(ComponentSet compSet)
        {
            if (compSet == null)
            {
                return ACCCode.ACCOK;
            }

            DateTime now = DateTime.Now;

            DbConnection conn = DataManager.DBHelper.GetConnection(DBHelper.DEFAULT);
            DbTransaction dbTrans = null;

            try
            {
                dbTrans = conn.BeginTransaction();
                UInt64 newComponentSetID = (UInt64)ACCSID.GetID(ACCSID.RECID_COMPONENTSET);

                //删除不在ItemPartNo列表中的数据

                //string partnoList = string.Join(" Or "
                //    , compSet.Items.ToList().Select(x => string.Format("( ItemPartNo = '{0}' and ItemRev = '{1}' and Line = '{2}' and OP = '{3}' and STN = '{4}' )"
                //                                                       , x.Value.BomItem.ItemPartNo
                //                                                       , x.Value.BomItem.ItemRev
                //                                                       , x.Value.BomItem.BomCfg.LineCfg.Line
                //                                                       , x.Value.BomItem.op
                //                                                       , _data.StnCfg.Name)).ToArray());

                //string sql = string.Format(TSQLHelper.GetSql("lotchangeprocess_deluselessbatchlotdata1"), partnoList, _data.StnCfg.LineCfg.Line, _data.StnCfg.OPCfg.OP, _data.StnCfg.Name);

                //DataManager.DBHelper.Update(dbTrans, false, sql);

                string sql = "";

                //删除数量为0的数据 
                //DELETE FROM ACC_LOT_BATCH WHERE QTY = 0
                DataManager.DBHelper.Update(dbTrans, false, TSQLHelper.GetSql("lotchangeprocess_deluselessbatchlotdata2"));

                //记录每种物料的第一个批次
                Dictionary<string, List<LotBatchData>> lstLotData = new Dictionary<string, List<LotBatchData>>();

                foreach (var setItem in compSet.Items.Values)
                {
                    setItem.LotBatchDatas.Clear();
                    /* 
                    SELECT LINE,
                           OP,
                           ITEMPARTNO,
                           ITEMREV,
                           LOT,
                           SUPPLIER_LOT,
                           QTY,
                           QTY_START,
                           RESERVED,
                           CTIME,
                           RECID,
                           STN,
                           FEEDERNO,
                           QTYPER
                      FROM ACC_LOT_BATCH
                     WHERE LINE = :1
                       AND OP = :2
                       AND ITEMPARTNO = :3
                       AND ITEMREV = :4
                       AND STN = :5
                     ORDER BY CTIME
                    */
                    sql = TSQLHelper.GetSql("lotchangeprocess_getfirstbatchlot");
                    object[] param = new object[]{
                        setItem.BomItem.BomCfg.LineCfg.Line
                        , setItem.BomItem.op
                        , setItem.BomItem.ItemPartNo
                        , setItem.BomItem.ItemRev
                        , _data.StnCfg.Name};

                    DataTable dtLot = DataManager.DBHelper.Query(dbTrans, sql, param);
                    lstLotData[setItem.BomItem.ItemPartNo] = new List<LotBatchData>() { };
                    if (dtLot != null && dtLot.Rows.Count > 0)
                    {
                        //1. 将ACC_LOT_BATCH数据加载到LotBatchDatas中  
                        for (int i = 0; i < dtLot.Rows.Count; i++)
                        {
                            LotBatchData lot = new LotBatchData();
                            lot.Line = dtLot.Rows[i]["LINE"].ToString();
                            lot.OP = dtLot.Rows[i]["OP"].ToString();
                            lot.ItemPartNo = dtLot.Rows[i]["ITEMPARTNO"].ToString();
                            lot.ItemRev = dtLot.Rows[i]["ITEMREV"].ToString();
                            lot.Lot = dtLot.Rows[i]["LOT"].ToString();
                            lot.Qty = double.Parse(dtLot.Rows[i]["QTY"].ToString());
                            lot.QtyStart = double.Parse(dtLot.Rows[i]["QTY_START"].ToString());
                            lot.Reserved = dtLot.Rows[i]["RESERVED"].ToString();
                            lot.CTime = DateTime.Parse(dtLot.Rows[i]["CTIME"].ToString());
                            lot.RecID = UInt64.Parse(dtLot.Rows[i]["RECID"].ToString());
                            lot.FeederNO = dtLot.Rows[i]["FEEDERNO"] == null ? "" : dtLot.Rows[i]["FEEDERNO"].ToString();

                            double qtytmp;
                            double.TryParse(dtLot.Rows[i]["QTYPER"].ToString(), out qtytmp);
                            lot.QtyPer = qtytmp;

                            setItem.LotBatchDatas.Add(lot);
                        }

                        //2. 获取第一个物料作为当前正在使用的物料
                        if (string.IsNullOrEmpty(setItem.BomItem.FeederNo))
                        {
                            LotBatchData lot = setItem.LotBatchDatas.FirstOrDefault();
                            lstLotData[setItem.BomItem.ItemPartNo].Add(lot);
                        }
                        else
                        {
                            foreach (string feeder in setItem.BomItem.FeederNo.Split(','))
                            {
                                string feederNo = feeder.Split('|')[0];
                                LotBatchData lot = setItem.LotBatchDatas.FirstOrDefault(l => l.FeederNO.Equals(feederNo));
                                lstLotData[setItem.BomItem.ItemPartNo].Add(lot); ;
                            }
                        }

                        //3.更新ComponentSet 和 LotTrack
                        foreach (LotBatchData lot in lstLotData[setItem.BomItem.ItemPartNo])
                        {
                            sql = TSQLHelper.GetSql("lotchangeprocess_insertcompset");
                            param = new object[]
                            {
                                now, 
                                lot.Line,
                                lot.OP, 
                                newComponentSetID.ToString(), 
                                lot.Lot,
                                lot.SupplierLot == null ? "" : lot.SupplierLot, 
                                lot.ItemPartNo, 
                                lot.ItemRev,
                                lot.Reserved == null ? "" : lot.Reserved, 
                                (null == _data.PartNo ? "0" : _data.PartNo.RuntimeID.ToString())
                            };

                            logger.Debug(CommUtils.FormatSQL(sql, param));
                            DataManager.DBHelper.Update(dbTrans, sql, param);

                            sql = TSQLHelper.GetSql("lotchangeprocess_insertlottrack1");
                            param = new object[]
                            {
                                lot.Qty, lot.QtyStart, lot.RecID.ToString()
                            };

                            logger.Debug(CommUtils.FormatSQL(sql, param));
                            if (DataManager.DBHelper.Update(dbTrans, sql, param) == 0)
                            {
                                sql = TSQLHelper.GetSql("lotchangeprocess_insertlottrack2");
                                param = new object[]
                                {
                                    lot.RecID.ToString(),
                                    now,
                                    lot.Line,
                                    lot.OP,
                                    lot.ItemPartNo,
                                    lot.ItemRev,
                                    lot.Lot,
                                    lot.SupplierLot == null ? "" : lot.SupplierLot,
                                    lot.QtyStart,
                                    lot.Qty,
                                    now,
                                    lot.Reserved == null ? "" : lot.Reserved,
                                    lot.FeederNO,
                                    lot.QtyPer
                                };

                                logger.Debug(CommUtils.FormatSQL(sql, param));
                                DataManager.DBHelper.Update(dbTrans, sql, param);
                            }
                        }
                    }
                }
                dbTrans.Commit();

                //4.将首个物料加载到内存
                compSet.ComponentSetID = newComponentSetID;

                foreach (var setItem in compSet.Items.Values)
                {
                    setItem.LotItems.Clear();
                    if (lstLotData[setItem.BomItem.ItemPartNo].Count < 1)
                    {
                        continue;
                    }

                    var lotdatas = lstLotData[setItem.BomItem.ItemPartNo].Where(x =>
                        x.Line == setItem.BomItem.BomCfg.LineCfg.Line
                        & x.OP == setItem.BomItem.op
                        & x.ItemPartNo == setItem.BomItem.ItemPartNo
                        & x.ItemRev == setItem.BomItem.ItemRev).ToList();

                    //Feeder会有多条，非Feeder只会有一条
                    if (lotdatas.Count > 0)
                    {
                        foreach (LotBatchData lot in lotdatas)
                        {
                            LotTrackItem lotItem = new LotTrackItem();
                            lotItem.RecID = lot.RecID;
                            lotItem.OP = lot.OP;
                            lotItem.ItemPartNo = lot.ItemPartNo;
                            lotItem.ItemRev = lot.ItemRev;
                            lotItem.Lot = lot.Lot;
                            lotItem.Supplier_Lot = lot.SupplierLot;
                            lotItem.Reserved = lot.Reserved;
                            lotItem.Qty = lot.Qty;
                            lotItem.QtyStart = lot.QtyStart;
                            lotItem.FirstTime = now;
                            setItem.LotItems.Add(lotItem);
                        }
                    }
                }

                return ACCCode.ACCOK;
            }
            catch (Exception ex)
            {
                logger.Error(ex.Message, ex);
                if (null != dbTrans)
                {
                    dbTrans.Rollback();
                }
                return ACCCode.Unload_ProcDataError;
            }
            finally
            {
                conn.Close();
            }
        }
    }
}